﻿using Serilog;
using Serilog.Core;
using Serilog.Events;
using Serilog.Sinks.Async;

namespace CUGroup.IOT.Unit.Ilog
{
    public class SerilogExample
    {
        public Logger logger = null;
        public SerilogExample()
        {
            //if (logger == null)
            //{
            //    logger = new LoggerConfiguration()
            //        .WriteTo.Async(a => a.Console(outputTemplate: "{Timestamp:HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}"))
            //        .WriteTo.Async(a => a.File("logs/myapp.log", outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}"))
            //        .CreateLogger();


            //}

        }
    }
    public class SeriLogHelper
    {
        /// <summary>
        /// 这段代码实现了一个使用 Serilog 记录日志的类 Logger。该类通过使用 Serilog 的 ILogger 和 LoggerConfiguration 实现了自定义的日志记录选项。在此基础上，Logger 还提供了一个 AppendLog 方法，可以将指定的日志消息添加到日志记录器中，并将其写入到日志文件中。同时，Logger 支持多进程共享日志文件，以解决多进程并发写入日志文件的问题。通过这些功能，Logger 类可以实现高效、可靠、线程安全的日志记录，并能够满足复杂的应用程序日志记录需求。
        /// </summary>
        public class Logger
        {
            private ILogger logger;

            /// <summary>
            /// 实例化ILogger
            /// </summary>
            /// <param name="ProjectName">该实例保存文件夹名称</param>
            public Logger(string ProjectName)
            {
                // 为每个线程创建独立的日志记录器，日志文件夹以项目名称命名
#pragma warning disable CA1416 // 验证平台兼容性
                logger = new LoggerConfiguration()
                    .MinimumLevel.Debug() // 设置最低日志级别
                    .MinimumLevel.Override("System", LogEventLevel.Information)
                    .WriteTo.Console()    // 输出日志到控制台
                    .WriteTo.EventLog("Application", restrictedToMinimumLevel: LogEventLevel.Warning)//将日志写入 Windows 事件日志                   
                    .WriteTo.Logger(Ic => ConfigureSerilog(Ic, ProjectName))
                   // 输出日志到文件，文件名中包含线程 ID
                   .CreateLogger();// 构造日志记录器
#pragma warning restore CA1416 // 验证平台兼容性
            }

            /// <summary>
            /// 日志配置
            /// </summary>
            /// <param name="loggerConfiguration"></param>
            /// <param name="ProjectName"></param>
            public void ConfigureSerilog(LoggerConfiguration loggerConfiguration, string ProjectName)
            {
                loggerConfiguration
                    .WriteTo.Logger(config => config
                    .WriteTo.Async(a => a//异步写入
                        .File(
                            "SeriLog/" + ProjectName +"/"+ DateTime.Now.ToString("yyyyMMdd") + "/.txt",
                            // 设置日志输出到文件中，文件名按天滚动，文件夹名称为日期加小时
                            rollingInterval: RollingInterval.Day,
                            rollOnFileSizeLimit: true,// 设置为 true，表示启用日志文件大小限制，当日志文件达到设定的大小后，会自动滚动到新的文件中。
                            fileSizeLimitBytes: 50_000_000, //设置每个日志文件的最大大小，单位是字节。这里的值是 10MB，即 10_000_000 字节。
                            retainedFileCountLimit: 200,//设置保留的日志文件数量上限，这里是 200，即最多保留最新的 200 个日志文件。
                            retainedFileTimeLimit: TimeSpan.FromDays(3),//设置日志文件的最长保留时间，这里是 7 天。
                            shared: true, // 多进程共享文件
                                          // 设置日志输出模板，包括时间戳、日志级别、日志消息、日志来源和异常信息
                            outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {NewLine}{Exception}"
                        )
                ));
            }

            /// <summary>
            /// 新增日志
            /// </summary>
            /// <param name="message">日志信息</param>
            /// <param name="logLevel">日志级别</param>
            public void AppendLog(string message,Exception ex=null, LogLevel logLevel = LogLevel.Info)
            {
                switch (logLevel)
                {
                    case LogLevel.Info:
                        logger.Information(message);
                        break;
                    case LogLevel.Warning:
                        logger.Warning(message);
                        break;
                    case LogLevel.Error:
                        logger.Error(ex,message);
                        break;
                    case LogLevel.Debug:
                        logger.Debug(message);
                        break;
                    case LogLevel.Fatal:
                        logger.Fatal(message);
                        break;
                }
            }
        }

        /// <summary>
        /// 日志级别
        /// </summary>
        public enum LogLevel
        {
            Info, Warning, Error, Debug, Fatal
        }
    }
}
